﻿using System;
using System.Threading;
using System.Diagnostics;
using System.Threading.Tasks;

namespace Domain.NetworkService
{
    public class NetworkServiceTest
    {
        public NetworkServiceTestID ID { get; private set; }
        TimeSpan timeout;
        INetworkServiceTest test;
        NetworkTestResult result;
        CancellationTokenSource cts;
        static int count;
        private Task innerTask;
        private static object _lock = new object();
        public NetworkServiceTest(NetworkServiceTestID id, INetworkServiceTest test)
        {
            this.ID = id;
            this.timeout = test.Timeout;
            this.test = test;
        }
        public Task Interval(TimeSpan timeout, Action action, CancellationToken token)
        {
            return Task.Factory.StartNew(() =>
                    {
                        while (true)
                        {
                            action();
                            if (token.WaitHandle.WaitOne(timeout))
                            {
                                lock (_lock) { --count; }
                                Console.WriteLine("[{0}] STOPED: {1}", count, this.ID);
                                break;
                            }
                        }
                    }, token, TaskCreationOptions.LongRunning, TaskScheduler.Default);
        }
        public void Run()
        {
            if (cts != null) // предотвращение запуска двух одинаковых задач
            {
                Stop();
            }
            innerTask = null;
            cts = new CancellationTokenSource();
            innerTask = Interval(timeout, Act, cts.Token);
            while (innerTask.Status != TaskStatus.Running) { Thread.Sleep(10); }
            lock (_lock) { ++count; }
            Console.WriteLine("[{0}] STARTED: {1}", count, ID.ToString());
        }
        private void Act()
        {
            result = test.Start();
            result.WriteToDB(this.ID.deviceName);
            EmailSender.checkAndSend(result, this.ID.deviceName);
        }
        public void Stop()
        {
            if (cts == null) // если тест не запущен, а устройство надо удалить.
            { return; }
            try
            {
                cts.Cancel();
            }
            catch (AggregateException x)
            {
                x.Handle(e => e is OperationCanceledException);
            }
        }
        public bool isActive()
        {
            if (innerTask != null && innerTask.Status.Equals(TaskStatus.Running))
            {
                return true;
            }
            return false;
        }
    }
}
